﻿using Microsoft.ClearScript.JavaScript;
using Microsoft.ClearScript.V8;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace ZGAssemblerLib;

public class JS_ClearScript
{
	private const string CorePath = "core.js";

	private static readonly V8ScriptEngine engine = new(V8ScriptEngineFlags.EnableTaskPromiseConversion);
	private static readonly dynamic assembler;

	private static readonly TaskCompletionSource<object> taskSource = new();
	private static readonly Action<object> onResolve;
	private static readonly Action<object> onReject;

	static JS_ClearScript()
	{
		if (!File.Exists(CorePath))
			throw new FileNotFoundException($"找不到核心文件 {CorePath}");

		onResolve = new Action<object>(result => taskSource.SetResult(result));
		onReject = new Action<object>(error => taskSource.SetException(new Exception(error.ToString())));

		var coreFile = File.ReadAllText(CorePath);

		engine.AddHostObject("console", new JSConsole());
		engine.AddHostType("TextEncoder", typeof(JSTextEncoder));
		engine.AddHostType("TextDecoder", typeof(JSTextDecoder));

		engine.Execute(coreFile);
		engine.Execute("var assembler = new zgassembler();");

		assembler = engine.Script.assembler;
		var fileUtils = assembler.fileUtils;

		fileUtils.ReadFile = new Func<string, byte[]>(JSHelper.ReadFile);
		fileUtils.SaveFile = new Action<string, byte[]>(JSHelper.SaveFile);
		fileUtils.PathType = new Func<string, string>(JSHelper.PathType);
		fileUtils.ShowMessage = new Action<string>(JSHelper.ShowMessage);
	}

	#region 切换平台
	public static void SwitchPlatform(string platform)
	{
		assembler.SwitchPlatform(platform);
	}
	#endregion 切换平台

	#region 编译文本
	/// <summary>
	/// 编译文本
	/// </summary>
	/// <param name="sourceFile"></param>
	/// <returns></returns>
	/// <exception cref="FileNotFoundException"></exception>
	public static short[] CompileText(string sourceFile)
	{
		if (!File.Exists(sourceFile))
			throw new FileNotFoundException($"找不到文件 {sourceFile}");

		var fileContent = File.ReadAllText(sourceFile, Encoding.UTF8);

		var promiseResult = assembler.CompileText(fileContent, sourceFile);
		var result = promiseResult.Result as ITypedArray<short>;
		return result?.ToArray();
	}
	#endregion 编译文本

	#region 获取所有错误
	public static void GetAllError()
	{
		var messages = assembler.diagnostic.GetExceptions() as IList<dynamic>;

		var orgColor = Console.ForegroundColor;
		Console.ForegroundColor = ConsoleColor.Red;
		foreach (var msg in messages)
		{
			Console.WriteLine($"文件: \"{msg.filePath}\"");
			Console.WriteLine($"第 {msg.line + 1} 行");
			Console.WriteLine(msg.message);
			Console.WriteLine();
		}
		Console.ForegroundColor = orgColor;

		messages = assembler.diagnostic.GetWarnings() as IList<dynamic>;
		Console.ForegroundColor = ConsoleColor.DarkYellow;
		foreach (var msg in messages)
		{
			Console.WriteLine($"文件: \"{msg.filePath}\"");
			Console.WriteLine($"第 {msg.line + 1} 行");
			Console.WriteLine(msg.message);
			Console.WriteLine();
		}
		Console.ForegroundColor = orgColor;
	}
	#endregion 获取所有错误
}